package org.example.seata.bs.product.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import lombok.AllArgsConstructor;
import org.example.seata.bs.api.dto.order.OrderInfoDto;
import org.example.seata.bs.api.entity.product.Product;
import org.example.seata.bs.api.service.product.impl.ProductServiceImpl;
import org.example.seata.bs.product.service.ProductEnhanceService;
import org.example.seata.common.core.constant.LKC;
import org.example.seata.common.core.util.ApiResp;
import org.example.seata.common.core.util.BusOp;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * @author hzq
 * @date 2021/12/1 10:06
 */
@Service
@Primary
@DS("product")
@AllArgsConstructor
public class ProductEnhanceServiceImpl extends ProductServiceImpl implements ProductEnhanceService {

    private final LockTemplate lockTemplate;

    @Override
    public ApiResp<Boolean> minusProductVirtualInventory(List<OrderInfoDto> orderInfoDtoList) {
        for (OrderInfoDto orderInfoDto : orderInfoDtoList) {
            LockInfo lock = lockTemplate.lock(LKC.Product.PRODUCT_VIRTUAL_INVENTORY.getLockKey(orderInfoDto.getProductId()));
            try {
                Product product = getById(orderInfoDto.getProductId());
                BusOp.mustNotNull(product);
                // 原有虚拟库存
                BigDecimal productVirtualInventory = BusOp.defaultValue(product.getProductVirtualInventory(), BigDecimal.ZERO);
                // 当前虚拟库存
                BigDecimal currentProductVirtualInventory = productVirtualInventory.subtract(orderInfoDto.getProductCount());
                // 当前虚拟库存小于0
                if (currentProductVirtualInventory.compareTo(BigDecimal.ZERO) < 0) {
                    return ApiResp.ofError("库存不足", Boolean.FALSE);
                }
                product.setProductVirtualInventory(currentProductVirtualInventory);
                BusOp.mustSucceed(updateById(product), "减少虚拟库存失败");
            } finally {
                lockTemplate.releaseLock(lock);
            }
        }
        return ApiResp.ofSuccess("减少虚拟库存成功", Boolean.TRUE);
    }

    @Override
    public ApiResp<Boolean> plusProductVirtualInventory(List<OrderInfoDto> orderInfoDtoList) {
        for (OrderInfoDto orderInfoDto : orderInfoDtoList) {
            LockInfo lock = lockTemplate.lock(LKC.Product.PRODUCT_VIRTUAL_INVENTORY.getLockKey(orderInfoDto.getProductId()));
            try {
                Product product = getById(orderInfoDto.getProductId());
                BusOp.mustNotNull(product);
                // 原有虚拟库存
                BigDecimal productVirtualInventory = BusOp.defaultValue(product.getProductVirtualInventory(), BigDecimal.ZERO);
                // 当前虚拟库存
                BigDecimal currentProductVirtualInventory = productVirtualInventory.add(orderInfoDto.getProductCount());
                product.setProductVirtualInventory(currentProductVirtualInventory);
                BusOp.mustSucceed(updateById(product), "增加虚拟库存失败");
            } finally {
                lockTemplate.releaseLock(lock);
            }
        }
        return ApiResp.ofSuccess("增加虚拟库存成功", Boolean.TRUE);
    }
}
